#pragma once
#include "data.h"

class MObj
{
public:

	MObj();
	virtual ~MObj();

	static void* operator new( size_t stSize);
	static void* operator new[](size_t stSize);

	static void operator delete( void *pvMem , size_t stElementSize);
	static void operator delete[]( void *pvMem, size_t stElementSize);

	inline static void* operator new( size_t, void* p){return p;}
	inline static void* operator new[]( size_t, void* p){return p;}
	inline static void operator delete( void *, void*){}
	inline static void operator delete[]( void *,void*){}
};


class RObj: public MObj
{
public:
	RObj()
		:mReferenceCount(0)
	{
	}

	virtual ~RObj();

	void IncRef ();
	void DecRef ();

	s32_t mReferenceCount;
};

#include "RefPtr.h"

// member offset
#define DataOffset( cls, member ) \
	( (s32_t)&((cls*)1)->member - 1)


struct ClassDef;

#define Ins_DeclareObj( TObject, TBaseClass) \
	Base_DeclareObj( TObject , TBaseClass);\
	static Obj* Create_##TObject()


#define Base_DeclareObj( TClass, TBaseClass) \
	DeclareObj( TClass);\
	typedef TBaseClass __superCls;\
	typedef TClass ThisClassType\


#define DeclareObj( TObject) \
	public:\
	static ClassDef* RTTI();\
	virtual ClassDef* GetClass(){ return TObject::RTTI(); };\
	typedef RefPtr< TObject> Ptr;\
	protected:\
	TObject();\
	virtual ~TObject();\


#define CreateObj( TObject)\
	Obj* TObject::Create_##TObject(){\
		return new TObject();\
	}

#define Base_NoCons( TObject)\
	ClassDef* TObject::RTTI() \
	{\
		static ClassDef _rtti_(#TObject, __superCls::RTTI(), 0);\
		return &_rtti_;\
	}	


#define Begin_Cons_Init( TObject)\
	TObject::TObject()\
	:__superCls()

#define Begin_Data_Init( TObject)\
	{}\
	TObject::~TObject()\
	{}\
	void TObject##_StaticInit()\
	{

#define Ins_NoCons( TObject)\
	CreateObj(TObject);\
	ClassDef* TObject::RTTI()\
	{\
		static ClassDef _rtti_(#TObject, __superCls::RTTI(), &TObject::Create_##TObject);\
		return &_rtti_;\
	}\
	

#define Ins_BeginObj( TObject) \
	Ins_NoCons( TObject);\
	TObject::TObject(ClassDef* cls):__superCls( cls ){}\
	TObject::~TObject(){}\
	void TObject##_StaticInit()\
	{\


#define Base_BeginObj( TObject) \
	Base_NoCons( TObject);\
	TObject::TObject():__superCls(){}\
	TObject::~TObject(){}\
	void TObject##_StaticInit()\
	{\

#define EndObj }\

struct PropDef;
struct PropData;
/*
*/

class Pack;
class Obj: public RObj
{
	DeclareObj( Obj);
public:

	template< typename T>
	bool IsTypeOf()
	{
		return IsTypeOf( T::RTTI());
	}

	bool IsTypeOf( ClassDef* cls);

	bool GetMemberData( const char* name, PropData&); 
	bool GetMemberData( PropDef* dataDef, PropData&); 

	virtual void PostLoad();

	Obj* Clone();
	virtual void CopyMemDataTo( Obj* dst, ClassDef* dataDefs);
	virtual void OnDataModified( PropDef* def);


	virtual void OnStream( Pack*);

	class DataListener
	{
	public:
		virtual void NotifyDataModified( Obj* obj, PropDef* def) = 0;
	};

	virtual DataListener* GetDataListener();
};


template< typename T>
T* obj_cast( Obj* obj)
{

	if(obj && obj->IsTypeOf( T::RTTI()))
	{
		return (T*)obj;
	}

	return 0;
}
